<script setup lang="ts">
import { ref } from 'vue';
import type { RequestFn, TransformFn } from '@/hooks/usePageList';
import { usePageList } from '@/hooks/usePageList';
import { iconsMapper } from './constants';
import type { EmptyStateKey } from './type';

const props = withDefaults(
  defineProps<{
    /**
     * 数据请求方法，接收分页参数，返回 Promise
     */
    request: RequestFn
    /**
     * 数据转换方法，对请求返回的数据进行转换
     */
    transform?: TransformFn
    /**
     * 分页大小，默认为10
     */
    size?: number
    /**
     * 是否开启滚动到底部自动加载更多，默认true
     */
    openScrollToBottom?: boolean
    /**
     * 是否自动初始化请求列表，默认true
     */
    isInit?: boolean
    /**
     * 列表高度（CSS值），默认fit-contents
     */
    height?: string
    /**
     * 空状态模式，决定显示何种空态，默认'list'
     */
    mode?: EmptyStateKey
    /**
     * 是否开启横向滚动，默认false
     */
    x?: boolean
    /**
     * 是否开启纵向滚动，默认false
     */
    y?: boolean
    /**
     * 是否异步等待操作（未使用/预留）
     */
    await?: boolean
    /**
     * 组件自定义样式（对象）
     */
    customStyle?: Record<string, string>
    /**
     * 是否显示“加载更多”按钮，默认false
     */
    showMore?: boolean
    /**
     * 是否显示空状态，默认true
     */
    showEmpty?: boolean
    /**
     * 是否显示滚动条，默认true
     */
    showScrollbar?: boolean
    /**
     * 是否显示组件，默认false
     */
    isShow?: boolean
    /**
     * 是否开启下拉刷新，默认false
     */
    refresherEnabled?: boolean
  }>(),
  {
    size: 10,
    openScrollToBottom: true,
    isInit: true,
    isShow: false,
    height: 'fit-contents',
    x: false,
    y: false,
    mode: 'list',
    transform: undefined,
    awaitR: false,
    customStyle: () => ({}),
    showMore: false,
    showEmpty: true,
    showScrollbar: true,
    refresherEnabled: false,
  },
)

const emit = defineEmits<{
  (e: 'scrolltolower'): void
  (e: 'refresherrefresh'): void
}>()

const { state, query, queryMore, refresh, clearList } = usePageList({
  request: props.request,
  transform: props.transform,
  size: props.size,
  openScrollToBottom: props.openScrollToBottom,
  isInit: props.isInit,
  awaitR: props.awaitR,
  isShow: props.isShow,
})

const isRefreshing = ref(false)

const handleRefresherRefresh = async () => {
  isRefreshing.value = true
  emit('refresherrefresh')
  try {
    await refresh()
  } finally {
    isRefreshing.value = false
  }
}

const getDataSource = () => state.list
defineExpose({
  query,
  queryMore,
  refresh,
  clearList,
  getDataSource,
  state,
})
</script>

<template>
  <scroll-view
    class="w-full"
    :class="{ 'scrollbar-hide': !showScrollbar }"
    :style="{ height, ...customStyle }"
    :scrollX="x"
    :scrollY="y || refresherEnabled"
    :showScrollbar="showScrollbar"
    :refresher-enabled="refresherEnabled"
    :refresher-triggered="isRefreshing"
    @scrolltolower="$emit('scrolltolower')"
    @refresherrefresh="handleRefresherRefresh"
  >
    <slot name="header" :state="state" />
    <slot :list="state.list" />
    <slot name="allList" :state="state" />
    <slot name="footer" :state="state">
      <view v-if="showMore && !state.isNone" class="w-full">
        <uv-load-more
          :status="
            state.loading
              ? 'loading'
              : state.totalCount < state.list.length
                ? 'loadmore'
                : 'nomore'
          "
          color="#ccc"
          loadingText="努力加载中，请先喝杯茶"
        />
      </view>
    </slot>
    <slot name="empty" :state="state">
      <view v-if="showEmpty" class="w-full">
        <view v-if="state.isNone" class="w-full pt-6">
          <uv-empty
            :mode="mode"
            :icon="iconsMapper[mode] || undefined"
            text="记录为空"
          />
        </view>
      </view>
    </slot>
  </scroll-view>
</template>

<style lang="scss" scoped>
.scrollbar-hide::-webkit-scrollbar {
  display: none;
  width: 0;
  height: 0;
  color: transparent;
}
</style>
